#!/usr/bin/env python3
"""
执行录制脚本文件
功能：
1. 扫描pwl文件夹下的录制脚本文件
2. 依次执行每个录制脚本
3. 收集执行结果并推送企业微信通知
"""

import os
import sys
import time
import logging
import subprocess
import glob
from typing import List, Dict, Any
from datetime import datetime

# 保证可以import到项目根目录下的config.py
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
from config import ENV, setup_logger

# 日志工具函数
def log_info(msg):
    logging.info(msg)

def log_error(msg):
    logging.error(msg)

def log_warning(msg):
    logging.warning(msg)

# 导入企业微信推送功能
try:
    from api.wechat_push import send_wechat_notification
    WECHAT_PUSH_AVAILABLE = True
except ImportError:
    log_error("企业微信推送模块导入失败，将跳过推送功能")
    WECHAT_PUSH_AVAILABLE = False

# 获取当前脚本所在的项目根目录
BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
PWL_DIR = os.path.join(BASE_DIR, 'pwl')


class ScriptExecutor:
    """录制脚本执行器"""
    
    def __init__(self):
        self.pwl_dir = PWL_DIR
        self.execution_results = []
        
    def find_record_scripts(self) -> List[str]:
        """
        查找pwl文件夹下的录制脚本文件
        :return: 录制脚本文件列表
        """
        # 查找test_record_***.py格式的文件
        record_pattern = os.path.join(self.pwl_dir, "test_record_*.py")
        record_scripts = glob.glob(record_pattern)
        
        # 也查找旧格式的test_*.py文件（排除run.py和execute_scripts.py）
        old_pattern = os.path.join(self.pwl_dir, "test_*.py")
        old_scripts = glob.glob(old_pattern)
        
        # 过滤掉非录制脚本文件
        exclude_files = ['run.py', 'execute_scripts.py']
        all_scripts = []
        
        for script in old_scripts:
            filename = os.path.basename(script)
            if filename not in exclude_files and not filename.startswith('test_record_'):
                all_scripts.append(script)
        
        # 合并新旧格式的脚本
        all_scripts.extend(record_scripts)
        
        # 按文件名排序
        all_scripts.sort()
        
        log_info(f"发现录制脚本文件: {len(all_scripts)} 个")
        for script in all_scripts:
            log_info(f"  - {os.path.basename(script)}")
            
        return all_scripts
    
    def execute_script(self, script_path: str) -> Dict[str, Any]:
        """
        执行单个录制脚本
        :param script_path: 脚本文件路径
        :return: 执行结果字典
        """
        script_name = os.path.basename(script_path)
        log_info(f"开始执行脚本: {script_name}")
        
        start_time = time.time()
        result = {
            'script_name': script_name,
            'script_path': script_path,
            'start_time': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            'success': False,
            'error_message': '',
            'execution_time': 0,
            'output': ''
        }
        
        try:
            # 执行Python脚本
            process = subprocess.run(
                [sys.executable, script_path],
                capture_output=True,
                text=True,
                encoding='utf-8',
                timeout=300  # 5分钟超时
            )
            
            execution_time = time.time() - start_time
            result['execution_time'] = round(execution_time, 2)
            result['output'] = process.stdout
            
            if process.returncode == 0:
                result['success'] = True
                log_info(f"✅ 脚本执行成功: {script_name} (耗时: {execution_time:.2f}s)")
            else:
                result['success'] = False
                result['error_message'] = process.stderr or "脚本执行返回非零状态码"
                log_error(f"❌ 脚本执行失败: {script_name} - {result['error_message']}")
                
        except subprocess.TimeoutExpired:
            execution_time = time.time() - start_time
            result['execution_time'] = round(execution_time, 2)
            result['error_message'] = "脚本执行超时（5分钟）"
            log_error(f"⏰ 脚本执行超时: {script_name}")
            
        except Exception as e:
            execution_time = time.time() - start_time
            result['execution_time'] = round(execution_time, 2)
            result['error_message'] = str(e)
            log_error(f"💥 脚本执行异常: {script_name} - {e}")
        
        return result
    
    def execute_all_scripts(self) -> List[Dict[str, Any]]:
        """
        执行所有录制脚本
        :return: 所有脚本的执行结果列表
        """
        scripts = self.find_record_scripts()
        
        if not scripts:
            log_warning("❗ 未找到任何录制脚本文件，跳过执行")
            print("❗ 提示：pwl文件夹下没有找到录制脚本文件")
            print("   请先运行 python pwl/run.py 来录制脚本")
            return []
        
        log_info(f"🚀 开始执行 {len(scripts)} 个录制脚本...")
        results = []
        failed_count = 0
        
        for i, script_path in enumerate(scripts, 1):
            script_name = os.path.basename(script_path)
            log_info(f"📋 执行进度: {i}/{len(scripts)} - {script_name}")
            
            result = self.execute_script(script_path)
            results.append(result)
            
            # 检查执行结果
            if result['success']:
                log_info(f"✅ [{i}/{len(scripts)}] {script_name} 执行成功")
            else:
                failed_count += 1
                log_error(f"❌ [{i}/{len(scripts)}] {script_name} 执行失败: {result['error_message']}")
                log_warning(f"⚠️ 脚本失败，继续执行下一个脚本...")
            
            # 脚本间间隔，避免资源冲突
            if i < len(scripts):
                log_info(f"⏳ 等待2秒后执行下一个脚本...")
                time.sleep(2)
        
        # 执行完成总结
        success_count = len(scripts) - failed_count
        log_info(f"\n📊 批量执行完成: 总共{len(scripts)}个脚本，成功{success_count}个，失败{failed_count}个")
        
        return results
    
    def generate_execution_summary(self, results: List[Dict[str, Any]]) -> Dict[str, Any]:
        """
        生成执行总结
        :param results: 执行结果列表
        :return: 执行总结字典
        """
        if not results:
            return {
                'total_scripts': 0,
                'success_count': 0,
                'failed_count': 0,
                'success_rate': 0,
                'total_time': 0,
                'executed_files': [],
                'failed_files': []
            }
        
        success_count = sum(1 for r in results if r['success'])
        failed_count = len(results) - success_count
        total_time = sum(r['execution_time'] for r in results)
        success_rate = round((success_count / len(results)) * 100, 1) if results else 0
        
        executed_files = [r['script_name'] for r in results]
        failed_files = [r['script_name'] for r in results if not r['success']]
        
        summary = {
            'total_scripts': len(results),
            'success_count': success_count,
            'failed_count': failed_count,
            'success_rate': success_rate,
            'total_time': round(total_time, 2),
            'executed_files': executed_files,
            'failed_files': failed_files
        }
        
        return summary
    
    def send_execution_notification(self, results: List[Dict[str, Any]]):
        """
        发送执行完成通知
        :param results: 执行结果列表
        """
        if not WECHAT_PUSH_AVAILABLE:
            log_info("企业微信推送功能不可用，跳过通知发送")
            return
        
        summary = self.generate_execution_summary(results)
        
        if summary['total_scripts'] == 0:
            # 没有脚本执行的情况
            custom_data = {
                'script_name': '无录制脚本',
                'executed_files': '未找到录制脚本文件',
                'execution_result': '跳过执行',
                'total_scripts': 0,
                'success_count': 0,
                'failed_count': 0,
                'success_rate': 0,
                'total_time': '0s'
            }
            
            try:
                success = send_wechat_notification(
                    template_type="execute",
                    result="跳过",
                    custom_data=custom_data
                )
                
                if success:
                    log_info("✅ 执行完成通知发送成功")
                else:
                    log_error("❌ 执行完成通知发送失败")
                    
            except Exception as e:
                log_error(f"发送执行完成通知异常: {e}")
            
            return
        
        # 准备推送数据
        overall_result = "成功" if summary['failed_count'] == 0 else "部分失败" if summary['success_count'] > 0 else "失败"
        
        # 格式化执行文件列表
        executed_files_str = "、".join(summary['executed_files'][:5])  # 最多显示5个文件名
        if len(summary['executed_files']) > 5:
            executed_files_str += f" 等{len(summary['executed_files'])}个文件"
        
        # 格式化失败文件列表
        failed_files_str = "无" if not summary['failed_files'] else "、".join(summary['failed_files'][:3])
        if len(summary['failed_files']) > 3:
            failed_files_str += f" 等{len(summary['failed_files'])}个"
        
        custom_data = {
            'script_name': f"批量执行({summary['total_scripts']}个脚本)",
            'executed_files': executed_files_str,
            'execution_result': overall_result,
            'total_scripts': summary['total_scripts'],
            'success_count': summary['success_count'],
            'failed_count': summary['failed_count'],
            'success_rate': summary['success_rate'],
            'total_time': f"{summary['total_time']}s",
            'failed_files': failed_files_str
        }
        
        try:
            success = send_wechat_notification(
                template_type="execute",
                result=overall_result,
                custom_data=custom_data
            )
            
            if success:
                log_info("✅ 执行完成通知发送成功")
            else:
                log_error("❌ 执行完成通知发送失败")
                
        except Exception as e:
            log_error(f"发送执行完成通知异常: {e}")
    
    def run(self):
        """
        主执行流程
        """
        log_info("=" * 60)
        log_info("🎬 开始执行录制脚本批处理任务")
        log_info("=" * 60)
        
        start_time = time.time()
        
        try:
            # 执行所有脚本
            results = self.execute_all_scripts()
            
            # 打印执行总结
            summary = self.generate_execution_summary(results)
            log_info("\n" + "=" * 40)
            log_info("📊 执行总结")
            log_info("=" * 40)
            log_info(f"📝 总脚本数: {summary['total_scripts']}")
            log_info(f"✅ 成功数量: {summary['success_count']}")
            log_info(f"❌ 失败数量: {summary['failed_count']}")
            log_info(f"🎯 成功率: {summary['success_rate']}%")
            log_info(f"⏱️ 总耗时: {summary['total_time']}s")
            
            if summary['failed_files']:
                log_info(f"💥 失败文件: {', '.join(summary['failed_files'])}")
            
            # 发送企业微信通知
            self.send_execution_notification(results)
            
            total_time = time.time() - start_time
            log_info(f"\n🎉 批处理任务完成！总耗时: {total_time:.2f}s")
            
        except Exception as e:
            log_error(f"💥 批处理任务执行异常: {e}")
            
            # 发送失败通知
            try:
                send_wechat_notification(
                    template_type="simple_error",
                    result="异常终止",
                    custom_data={
                        'error_message': str(e),
                        'script_name': '录制脚本批处理'
                    }
                )
            except:
                pass


def main():
    """主函数"""
    setup_logger()
    
    executor = ScriptExecutor()
    executor.run()


if __name__ == "__main__":
    main()
